package com.tul.vapp.servicecenter.service.impl;

import com.tul.cusa.common.util.DateUtil;
import com.tul.cusa.common.util.ListUtil;
import com.tul.vapp.servicecenter.dao.IAppDao;
import com.tul.vapp.servicecenter.dao.IItemDao;
import com.tul.vapp.servicecenter.dao.INamespaceDao;
import com.tul.vapp.servicecenter.dao.IReleaseAppDao;
import com.tul.vapp.servicecenter.entity.App;
import com.tul.vapp.servicecenter.entity.AppVo;
import com.tul.vapp.servicecenter.entity.Namespace;
import com.tul.vapp.servicecenter.entity.Status;
import com.tul.vapp.servicecenter.service.IAppService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 操作数据库中的APP
 *
 * @author wwxiang
 * @since 2018/1/4.
 */
@Service
public class AppService implements IAppService {

    private static final Logger LOGGER = LoggerFactory.getLogger(AppService.class);

    @Autowired
    private IAppDao appDao;

    @Autowired
    private IReleaseAppDao releaseAppDao;

    @Autowired
    private INamespaceDao namespaceDao;

    @Autowired
    private IItemDao iItemDao;

    @Override
    public List<App> getApps() {
        return appDao.getApps();
    }

    @Override
    public List<AppVo> getAppVos() {
        List<AppVo> appVos = new ArrayList();
        for (App app : appDao.getApps()) {
            AppVo appVo = new AppVo();
            appVo.setId(app.getId());
            appVo.setAppId(app.getAppId());
            appVo.setAppName(app.getAppName());
            appVo.setCreateTime(app.getCreateTime());
            appVo.setStatus(app.getStatus());
            if (app.getAppId().equals("ems-proxy")) {
                appVo.setEmsProxy(true);
            }
            List<Namespace> params = namespaceDao.getNamespaces(app.getAppId());
            appVo.setParams(params);
            appVos.add(appVo);
        }
        return appVos;
    }

    @Override
    public List<App> getReleaseApps() {
        return releaseAppDao.getApps();
    }

    @Override
    public App getApp(String appId) {
        return appDao.getApp(appId);
    }

    @Override
    public void deleteCascade(String appId) {
        appDao.deleteApp(appId);
        namespaceDao.deleteNamespace(appId);
        iItemDao.deleteItemInApp(appId);
    }

    @Override
    public void publish(String appId) {
        App app = appDao.getApp(appId);
        app.setUpdateTime(DateUtil.format(new Date(), DateUtil.DATE_TIME_FORMAT));
        if (app.getStatus() == Status.DELETE) {
            // 已标记删除的，操作表和发布表都删除对应记录
            appDao.deleteApp(appId);
            releaseAppDao.deleteApp(appId);
        } else if (app.getStatus() == Status.INSERT) {
            // 标记为新增的，操作表 状态更新为PUBLISHED， release表增加app记录
            app.setStatus(Status.PUBLISHED);
            appDao.updateApp(app);
            releaseAppDao.addApp(app);
        } else if (app.getStatus() == Status.MODIFY) {
            // 标记为修改的，操作表 状态改为PUBLISHED,然后用此数据去更新release表
            app.setStatus(Status.PUBLISHED);
            appDao.updateApp(app);
            // release表中已存在则更新，否则新增
            App release = releaseAppDao.getApp(appId);
            if (release != null) {
                releaseAppDao.updateApp(app);
            } else {
                releaseAppDao.addApp(app);
            }

        }
    }

    @Override
    public void rollback(String appId) {
        App app = appDao.getApp(appId);
        if (app.getStatus() == Status.DELETE) {
            // 标记为删除的，操作表的状态回退到published
            app.setStatus(Status.PUBLISHED);
            appDao.updateApp(app);
        } else if (app.getStatus() == Status.INSERT) {
            // 标记为新增的，回退时，只需将操作表数据删除
            appDao.deleteApp(app.getAppId());
        } else if (app.getStatus() == Status.MODIFY) {
            // 标记为修改的，根据发布表中的数据回退
            App releaseApp = releaseAppDao.getApp(appId);
            appDao.updateApp(releaseApp);
        }

    }

    /**
     * 一致性检查，确保发布表和操作表一致
     */
    @Override
    public void sanityCheck() {

        // 已发布的数据
        List<App> appsReleaseObj = releaseAppDao.getApps();
        List<String> appsRelease = new ArrayList<>();
        for (App a : appsReleaseObj) {
            appsRelease.add(a.getAppId());
        }

        // 操作表内的数据
        List<App> appsObj = appDao.getApps();
        List<String> appsDb = new ArrayList<>();
        for (App a : appsObj) {
            appsDb.add(a.getAppId());
        }

        // 发布表比操作表里多，是需要处理的
        List<String> adds = ListUtil.subtract(appsRelease, appsDb);
        for (String add : adds) {
            App a = releaseAppDao.getApp(add);
            appDao.addApp(a);
        }
    }
}
